<!--
    @Title: LeaferApp
    @Author  dudalei
    @Package
    @Date  2024/10/14 09:37
    @description: 画布基础组件
-->
<script setup lang="ts">
import { markRaw, onBeforeUnmount, provide, shallowRef, useTemplateRef } from 'vue'
import { App, type ILeaferConfig } from 'leafer-ui'
import '@leafer-in/state'
import 'leafer-editor'
import '@leafer-in/view'
import {
  getMaxMinZIndextKey,
  LeaferInjectKey,
  setMaxMinZIndextKey,
} from '@/components/LeaferApp/LeaferInjectKeys'

import dataJson from '../data.json'
import { loadAsyncComponent } from '@/utils/components'

const LeaferEditor = loadAsyncComponent(() => import('./LeaferEditor.vue'))
const LeaferRuler = loadAsyncComponent(() => import('./LeaferRuler.vue'))
const LeaferTooltip = loadAsyncComponent(() => import('./LeaferTooltip.vue'))
const LeaferForm = loadAsyncComponent(() => import('./LeaferForm.vue'))
interface Props {
  // 是否显示编辑器
  editor?: boolean
  // 是否显示标尺
  rule?: boolean
  // 编辑面板id
  editId: string
  // 是否展示编辑面板
  showEditForm?: boolean
  // 背景颜色
  fill?: string
  // 是否平滑渲染
  smooth?: boolean
  // 网格地面
  ground?: ILeaferConfig
}
const props = withDefaults(defineProps<Props>(), {
  editor: false,
  // 是否显示标尺
  rule: false,
  fill: '#242424',
  smooth: true,
  // ground: { type: 'board' }
})

// 是否显示画布
const showLeafer = ref(false)
const leaferContainerRef = useTemplateRef<HTMLHtmlElement>('leaferContainer')
const { width, height } = useElementSize(leaferContainerRef)
// 画布元素
const leaferViewRef = useTemplateRef<HTMLHtmlElement>('leaferViewRef')

const leaferApp = shallowRef<App | undefined>()
provide(LeaferInjectKey, leaferApp)

// 最大级别和最小级别
const maxZIndex = {
  min: 0,
  max: 0,
}
const getMaxMinZIndex = () => {
  return maxZIndex
}
const setMaxMinZIndex = (min: number, max: number) => {
  maxZIndex.min = min
  maxZIndex.max = max
}
provide(getMaxMinZIndextKey, getMaxMinZIndex)
provide(setMaxMinZIndextKey, setMaxMinZIndex)

/**
 * 获取最大值和最小值
 * @param data
 */
const getZIndex = (data: any[]) => {
  const zIndexs: number[] = []
  data.forEach((item: any) => {
    zIndexs.push(item.zIndex || 0)
    if (item.children) {
      const minMax = getZIndex(item.children)
      zIndexs.push(...minMax)
    }
  })
  return zIndexs
}

/**
 *初始化画布
 */
const initLeafer = () => {
  // 创建元素
  leaferApp.value = markRaw(
    new App({
      view: leaferViewRef.value as HTMLHtmlElement,
      width: width.value,
      height: height.value,
      // tree: {},
      tree: {},
      editor: {},
      ground: props.ground,
      fill: props.fill,
      smooth: props.smooth,
      // 是否手机端优化
      // mobile: true,
      wheel: { zoomMode: 'mouse' },
    })
  )

  // TODO  这里使用的假数据 正式使用需要通过参数传递过来
  if (dataJson) {
    leaferApp.value.tree.set(dataJson as any)
    const zInexs = getZIndex(dataJson.children)
    setMaxMinZIndex(Math.min(...zInexs), Math.max(...zInexs))
    return
  }
}
const init = useDebounceFn(() => {
  console.log('初始化')
  showLeafer.value = true
  nextTick().then(initLeafer)
}, 500)

watch(width, init)
const destroy = () => {
  console.log('销毁画布')
  if (!leaferApp.value) {
    return
  }
  leaferApp.value.destroy()
}
onBeforeUnmount(() => {
  // 销毁资源
  destroy()
})

/**
 * 导出json
 */
const exportJson = () => {
  if (!leaferApp.value) {
    return
  }
  const data = leaferApp.value.tree?.toString()
  console.log('data', data)
}

const leaferEditorRef = useTemplateRef<typeof LeaferEditor>('leaferEditorRef')

const editFn = computed(() => {
  if (!leaferEditorRef.value) {
    return { dragover: () => {}, drop: () => {} }
  }
  return leaferEditorRef.value
})

/**
 * 显示适合大小
 */
const fit = () => {
  if (!leaferApp.value) {
    return
  }
  leaferApp.value.tree.zoom('fit', 100)
}
/**
 * 导出方法
 */
defineExpose({ exportJson, fit })
</script>

<template>
  <div class="leafer-app" ref="leaferContainer">
    <el-button @click="exportJson" style="position: absolute; z-index: 1">导出json</el-button>
    <!--    <el-button @click="destroy" style="position: absolute; left: 200px; z-index: 2"
      >销毁测试</el-button
    >-->

    <div
      v-if="showLeafer"
      @dragover="editFn.dragover"
      @drop="editFn.drop"
      class="leafer-container"
      ref="leaferViewRef"
    ></div>
    <LeaferEditor v-if="props.editor" ref="leaferEditorRef"></LeaferEditor>
    <LeaferRuler v-if="props.rule"></LeaferRuler>
    <LeaferTooltip></LeaferTooltip>
    <Teleport :to="`#${props.editId}`" v-if="props.showEditForm">
      <LeaferForm></LeaferForm>
    </Teleport>
    <slot></slot>
  </div>
</template>

<style lang="scss" scoped>
.leafer-app {
  width: 100%;
  height: 100%;
  position: relative;

  .leafer-container {
    //position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
}
</style>
